package com.cn.common;

import com.cn.file.CountDownLatch2;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class ServerThread implements Runnable {

    private static final long JOIN_TIME = 90 * 1000;
    protected CountDownLatch2 waitPoint = new CountDownLatch2(1);
    private Thread thread;
    //false:服务正在运行 true:服务停止
    private volatile boolean stopped = false;
    protected volatile AtomicBoolean hasNotified = new AtomicBoolean(false);

    public ServerThread() {
        this.thread = new Thread(this, this.getServiceName());
    }

    public void start() {
        this.thread.start();
    }

    /**
     * 停止线程
     */
    public void stop() {
        stop(false);
    }

    public void stop(boolean interrupt) {
        if (this.hasNotified.compareAndSet(false, true)) {
            this.waitPoint.countDown();
        }
        if (interrupt) {
            this.thread.interrupt();
        }
    }

    public void shutDown() {
        this.shutDown(false);
    }

    public void shutDown(boolean interrupt) {
        this.stopped = true;
        if (this.hasNotified.compareAndSet(false, true)) {
            this.waitPoint.countDown();
        }
        try {
            if (interrupt) {
                this.thread.interrupt();
            }
            if (!this.thread.isDaemon()) {
                //如果不是主线程，那么让子线程执行完了，在继续主线程
                this.thread.join(this.getJointime());
            }
        } catch (Exception e) {

        }
    }

    public void makeStop() {
        this.stopped = true;
    }

    public void wakeup() {
        if (this.hasNotified.compareAndSet(false, true)) {
            //可以调用run
            this.waitPoint.countDown();
        }
    }

    protected void waitForRunning(long interval) {
        if (this.hasNotified.compareAndSet(true, false)) {
            return;
        }
        this.waitPoint.reset();
        try {
            this.waitPoint.await(interval, TimeUnit.MILLISECONDS);
        } catch (Exception e) {

        } finally {
            hasNotified.set(false);
            onWaitEnd();
        }
    }


    protected void onWaitEnd() {

    }

    public abstract String getServiceName();

    public long getJointime() {
        return JOIN_TIME;
    }

    public boolean isStopped() {
        return stopped;
    }
}
